import { Table } from "./interface";
import { reactive, computed, onMounted, toRefs, ref } from "vue";
import { ElMessage } from "element-plus";

/**
 * @description table 页面操作方法封装
 * @param {Function} api 获取表格数据 api 方法(必传)
 * @param {Object} initParam 获取数据初始化参数(不必传，默认为{})
 * @param {Boolean} isPageable 是否有分页(不必传，默认为true)
 * @param {Boolean} initData 是否默认加载数据，默认true
 * @param {Array} deep 是否嵌套属性
 * */
export const useTable = (api: (params: any) => Promise<any>, initParam: object = {}, isPageable: boolean = true, initData: boolean = true, deep = '') => {
	const state = reactive<Table.TableStateProps>({
		// 表格数据
		tableData: [],
		// 是否展开更多搜索框
		searchShow: false,
		// 分页数据
		pageable: {
			// 当前页数
			current: 1,
			// 每页显示条数
			size: 20,
			// 总条数
			total: 0
		},
		// 查询参数(只包括查询)
		searchParam: {},
		// 初始化默认的查询参数
		initSearchParam: {},
		// 总参数(包含分页和查询参数)
		totalParam: {},
	});
	//记录当前总数
	const totalRef = ref<number>(0), extendData = ref<any>({});

    //数据加载状态
    let loading = ref(false)

	/**
	 * @description 分页查询参数(只包括分页和表格字段排序,其他排序方式可自行配置)
	 * */
	const pageParam = computed({
		get: () => {
			return {
				current: state.pageable.current,
				size: state.pageable.size
			};
		},
		set: (newVal: any) => {
			console.log("我是分页更新之后的值", newVal);
		}
	});

	// 初始化的时候需要做的事情就是 设置表单查询默认值 && 获取表格数据(reset函数的作用刚好是这两个功能)
	onMounted(() => {
		initData && reset();
	});

	/**
	 * @description 获取表格数据
	 * @return void
	 * */
	const getTableList = async () => {
		try {
			for(let key in initParam) {
				if(!initParam[key] && initParam[key] !== 0) {
					ElMessage.error('初始参数存在空值');
					return;
				}
			}
            loading.value = true
			// 先更新查询参数
			updatedTotalParam();
			const param = Object.assign({}, initParam, state.totalParam);
			const res = await api(param);
            if(res) {
                const { data, extend } = res;
				extendData.value = extend;
				
                let records = isPageable ? data.records : data;
				const deeps = deep.split(',');
				if(deeps.length > 0) {
					for(let item of records) {
						for(let key of deeps) {
							let keyValue = item[key];
							if(keyValue) {
								for(let k in keyValue) {
									if(keyValue[k] || keyValue[k] === 0) {
										item[key+k] = keyValue[k]
									}
								}
								delete item[key]
							}
						}
					}
				}
				state.tableData = records;
                // 解构后台返回的分页数据(如果有分页更新分页信息)
                const { current, size, total } = data;
				if(current === 1) {
					totalRef.value = total
				}
                isPageable && updatePageable({ current, size, total: totalRef.value });
            }
		} catch (error) {
			console.log(error);
		} finally {
            loading.value = false
        }
	};

	/**
	 * @description 更新查询参数
	 * @return void
	 * */
	const updatedTotalParam = () => {
		state.totalParam = {};
		// 处理查询参数，可以给查询参数加自定义前缀操作
		let nowSearchParam: { [propName: string]: any } = {};
		// 防止手动清空输入框携带参数（可以自定义查询参数前缀）
		for (let key in state.searchParam) {
			// * 某些情况下参数为 false/0 也应该携带参数
			if (state.searchParam[key] || state.searchParam[key] === false || state.searchParam[key] === 0) {
				nowSearchParam[key] = state.searchParam[key];
			}
		}
		Object.assign(state.totalParam, nowSearchParam, isPageable ? pageParam.value : {});
	};

	/**
	 * @description 更新分页信息
	 * @param {Object} resPageable 后台返回的分页数据
	 * @return void
	 * */
	const updatePageable = (resPageable: Table.Pageable) => {
		Object.assign(state.pageable, resPageable);
	};

	/**
	 * @description 表格数据查询
	 * @return void
	 * */
	const search = () => {
		state.pageable.current = 1;
		getTableList();
	};

	/**
	 * @description 表格数据重置
	 * @return void
	 * */
	const reset = () => {
		state.pageable.current = 1;
		state.searchParam = {};
		// 重置搜索表单的时，如果有默认搜索参数，则重置默认的搜索参数
		Object.keys(state.initSearchParam).forEach(key => {
			state.searchParam[key] = state.initSearchParam[key];
		});
		getTableList();
	};

	/**
	 * @description 每页条数改变
	 * @param {Number} val 当前条数
	 * @return void
	 * */
	const handleSizeChange = (val: number) => {
		state.pageable.current = 1;
		state.pageable.size = val;
		getTableList();
	};

	/**
	 * @description 当前页改变
	 * @param {Number} val 当前页
	 * @return void
	 * */
	const handleCurrentChange = (val: number) => {
		state.pageable.current = val;
		getTableList();
	};

	return {
		...toRefs(state),
		getTableList,
		extendData,
		search,
		reset,
        loading,
		handleSizeChange,
		handleCurrentChange
	};
};
